﻿using Beaker.FileSystem;
using Beaker.FileSystem.InMemory;
using Beaker.Specs;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenCube.IO.Overload;
using OpenCube.IO.Specs.Builders;
using OpenCube.IO.Specs.Helpers;

namespace OpenCube.IO.Specs
{
	[TestClass]
	internal sealed class OverloadingFileSystemSpecs
		: SpecsFor<OverloadingFileSystem, OverloadingFileSystemBuilder>
	{
		[TestMethod]
		public void WhenFileIsAvailableInOverrideFolderThatIsTheFileToReturn()
		{
			var mem = new InMemoryFileSystem();

			IFolder rootFolder = mem.CreateFolder("rootFolder");
			IFile rootFile = rootFolder.CreateFile("GetMeFromOverride.txt");
			rootFile.WriteText("Root");

			IFolder overrideFolder = mem.CreateFolder("overrideFolder");
			IFile overrideFile = overrideFolder.CreateFile("GetMeFromOverride.txt");
			overrideFile.WriteText("Override");

			BuildSubject
				.AddFolder(rootFolder)
				.AddFolder(overrideFolder)
				.Build();

			IFile file = Subject.GetFile("GetMeFromOverride.txt");

			file.OpenText().ReadLine()
				.Should().Be("Override", because: "the file is available in the override folder");
		}

		[TestMethod]
		public void WhenFileIsOnlyAvailableInRootFolderTheRootFileIsReturned()
		{
			var mem = new InMemoryFileSystem();

			IFolder rootFolder = mem.CreateFolder("rootFolder");
			IFile rootFile = rootFolder.CreateFile("GetMeFromRoot.txt");
			rootFile.WriteText("Root");

			IFolder overrideFolder = mem.CreateFolder("overrideFolder");
			IFile overrideFile = overrideFolder.CreateFile("SomeDifferentName.txt");
			overrideFile.WriteText("Override");

			BuildSubject
				.AddFolder(rootFolder)
				.AddFolder(overrideFolder)
				.Build();

			IFile file = Subject.GetFile("GetMeFromRoot.txt");

			file.OpenText().ReadLine()
				.Should().Be("Root", because: "the file is available in the override folder");
		}

		[TestMethod]
		public void WhenFolderRetrievedAndThenGettingFolderItStillWorksWithOverloading()
		{
			// arrange
			var mem = new InMemoryFileSystem();

			IFolder rootFolder = mem.CreateFolder("rootFolder");
			IFolder subFolderInRoot = rootFolder.CreateFolder("SubFolder");
			IFile rootFileWithOverload = subFolderInRoot.CreateFile("filewith.txt");
			rootFileWithOverload.WriteText("RootWith");
			IFile rootFileWithoutOverload = subFolderInRoot.CreateFile("filewithout.txt");
			rootFileWithoutOverload.WriteText("RootWithout");

			IFolder overrideFolder = mem.CreateFolder("overrideFolder");
			IFolder subFolderInOverride = overrideFolder.CreateFolder("SubFolder");
			IFile overrideFile = subFolderInOverride.CreateFile("filewith.txt");
			overrideFile.WriteText("Override");

			BuildSubject
				.AddFolder(rootFolder)
				.AddFolder(overrideFolder)
				.Build();

			// act
			IFolder folder = Subject.GetFolder("SubFolder");

			// assert
			IFile fileWith = folder.GetFile("filewith.txt");
			fileWith.OpenText().ReadLine()
				.Should().Be("Override");

			IFile fileWithout = folder.GetFile("filewithout.txt");
			fileWithout.OpenText().ReadLine()
				.Should().Be("RootWithout");
		}

		[TestMethod]
		public void GetActualParentFolderReturnsTheFolderTheOverloadedFileCameFrom()
		{
			var mem = new InMemoryFileSystem();

			IFolder rootFolder = mem.CreateFolder("rootFolder");
			rootFolder.CreateFile("GetMeFromOverride.txt");
			rootFolder.CreateFile("GetMeFromRoot.txt");

			IFolder overrideFolder = mem.CreateFolder("overrideFolder");
			overrideFolder.CreateFile("GetMeFromOverride.txt");

			BuildSubject
				.AddFolder(rootFolder)
				.AddFolder(overrideFolder)
				.Build();

			IFile file = Subject.GetFile("GetMeFromOverride.txt");
			IFile file2 = Subject.GetFile("GetMeFromRoot.txt");

			file.ParentFolder
				.Should().NotBeSameAs(overrideFolder);
			file.GetActualParentFolder()
				.Should().BeSameAs(overrideFolder);

			file2.ParentFolder
				.Should().NotBeSameAs(rootFolder);
			file2.GetActualParentFolder()
				.Should().BeSameAs(rootFolder);

			file.ParentFolder
				.Should().BeSameAs(file2.ParentFolder);
		}

		[TestMethod]
		public void WhenCallingGetActualParentFolderOnNonOverloadingFileTheNormalParentFolderIsReturned()
		{
			var mem = new InMemoryFileSystem();
			IFolder rootFolder = mem.CreateFolder("rootFolder");
			IFile file = rootFolder.CreateFile("GetMeFromOverride.txt");

			file.GetActualParentFolder()
				.Should().BeSameAs(file.ParentFolder)
				.And.BeSameAs(rootFolder);
		}
	}
}
